package com.tarena.platform.email;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 发送邮件的多线程
 * 
 * @author octopus
 *
 */
public class MailThreadConfig extends Thread {
	private static final Logger LOGGER = LoggerFactory.getLogger(MailThreadConfig.class);

	// 配置参数类
	private static Map<String, String> proMap = new HashMap<>();
	private static MailThreadConfig instance = new MailThreadConfig();
	// 邮件端口号
	private static Session mailSession;
	private static Transport transport;
	private Executor executor = Executors.newSingleThreadExecutor();
	private LinkedBlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
	public static String apiUser = null;
	public static String apiKey = null;
	/** 沉睡时间，长时间不发送邮件现成沉睡 */
	public static int SLEEP_TIME = 10000;
	static {
		try {
			// 配置javamail
			Properties props = System.getProperties();
			// 配置javamail
			props.setProperty("mail.transport.protocol", getValue("mail.transport.protocol"));
			props.put("mail.smtp.host", getValue("mail.smtp.host"));
			props.put("mail.smtp.port", getValue("mail.smtp.port"));
			props.setProperty("mail.smtp.auth", getValue("mail.smtp.auth"));
			props.put("mail.smtp.connectiontimeout", getValue("mail.smtp.connectiontimeout")); // 单位：毫秒
			props.put("mail.smtp.timeout", getValue("mail.smtp.timeout")); // 单位：毫秒
			props.setProperty("mail.mime.encodefilename", getValue("mail.mime.encodefilename"));
			// 使用api_user和api_key进行验证
			apiUser = getValue("email.user");
			apiKey = getValue("email.password");

			mailSession = Session.getInstance(props, new Authenticator() {
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(apiUser, apiKey);
				}
			});
		} catch (Exception e) {
			LOGGER.error("init email service error.", e);
		}
	}

	/* 私有构造方法，防止被实例化 */
	private MailThreadConfig() {
		System.out.println("启动");
		this.start();
	}

	// 获取配置文件，初始化sender；
	public static MailThreadConfig getInstance() {
		return instance;
	}

	public void run() {
		LOGGER.info("start sms service ");
		Runnable r;
		try {// &&!Thread.currentThread().isInterrupted()
			for (;;) {
				while ((r = tasks.take()) != null) {
					executor.execute(r);
				}
				SLEEP_TIME *= 10;
				// Thread.currentThread();
				Thread.sleep(SLEEP_TIME);
			}
		} catch (InterruptedException e) {
			LOGGER.error("InterruptedException in sms service", e);
		}
	}

	/**
	 * 简单下发
	 * 
	 * @param to
	 * @param content
	 * @return
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	private void sendEmail(String to, String subject, String content) {
		SendEmailThread sendEmailThread = new SendEmailThread(to, subject, content);
		try {
			tasks.put(sendEmailThread);
			Thread.currentThread().notify();
		} catch (InterruptedException e) {
			LOGGER.error("send email service add task error.", e);
		}
	}

	/**
	 * 简单下发可以指定多个用户
	 * 
	 * @param toList
	 * @param subject
	 * @param content
	 */
	public void sendEmailList(List<String> toList, String subject, String content) {
		SendMessageThread message = new SendMessageThread(toList, subject, content);
		(new Thread(message)).start();
	}

	/**
	 * 异步发送邮件内部类
	 *
	 */
	class SendMessageThread extends Thread {
		List<String> toList;
		String subject;
		String content;

		public SendMessageThread(List<String> toList, String subject, String content) {
			this.toList = toList;
			this.subject = subject;
			this.content = content;
		}

		String smsmsg = "";

		public void run() {
			synchronized (smsmsg) {
				for (String to : toList) {
					sendEmail(to, subject, content);
				}
			}
		}
	}

	/**
	 * 异步发送邮件内部类
	 *
	 */
	class SendEmailThread extends Thread {
		String to;
		String subject;
		String content;

		public SendEmailThread(String to, String subject, String content) {
			this.to = to;
			this.subject = subject;
			this.content = content;
		}

		String smsmsg = "";

		public void run() {
			synchronized (smsmsg) {
				try {
					// 添加html形式的邮件正文
					BodyPart part1 = new MimeBodyPart();
					part1.setHeader("Content-Type", "text/html;charset=UTF-8");
					part1.setHeader("Content-Transfer-Encoding", "base64");
					part1.setContent(content, "text/html;charset=UTF-8");
					Multipart multipart = new MimeMultipart("alternative");
					multipart.addBodyPart(part1);

					MimeMessage message = new MimeMessage(mailSession);
					message.setContent(multipart);

					// 发信人，用正确邮件地址替代 netpay@trusdom.com
					message.setFrom(new InternetAddress(apiUser, apiUser, "UTF-8"));
					// 收件人地址，用正确邮件地址替代
					message.addRecipient(RecipientType.TO, new InternetAddress(to));
					// 邮件主题
					message.setSubject(subject, "UTF-8");
					LOGGER.info("send email to " + to + " subject " + subject);
					// 连接sendcloud服务器，发送邮件
					transport = mailSession.getTransport();
					transport.connect();
					transport.sendMessage(message, message.getRecipients(RecipientType.TO));
					transport.close();
				} catch (Exception e) {
					LOGGER.error("send email to " + to + " subject " + subject, e);
				}
			}
		}
	}

	/** 获取配置参数 **/
	public static String getValue(String key) {
		if (proMap == null || proMap.isEmpty()) {
			proMap = PropertiesReader.cacheProperties("platform_email.properties");
		}
		if (key == null || key.isEmpty()) {
			return null;
		}
		return proMap.get(key);
	}

	public static void main(String[] args) {
		List<String> emailList = new ArrayList<String>();
		emailList.add("340417593@qq.com");
		MailThreadConfig.getInstance().sendEmailList(emailList, "开发人员测试", "我自己能发送邮件了");
	}
}
